package com.xingchi.tornado.security.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xingchi.tornado.security.handler.LoginPostProcessor;
import com.xingchi.tornado.security.model.LoginParameter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * 统一认证拦截器
 *
 * @author xingchi
 * @date 2025/3/9 20:04
 */
@Slf4j
public class UnifiedAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private List<LoginPostProcessor<Authentication>> loginPostProcessors;
    private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login", "POST");

    public void setLoginPostProcessors(List<LoginPostProcessor<Authentication>> loginPostProcessors) {
        this.loginPostProcessors = loginPostProcessors;
    }

    public UnifiedAuthenticationFilter() {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
    }

    public UnifiedAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    public UnifiedAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
        super(requiresAuthenticationRequestMatcher);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {

        // 是否是POST请求
        if (!"POST".equals(request.getMethod())) {
            throw new IllegalArgumentException("Authentication method not supported: " + request.getMethod());
        }

        // 读取请求参数
        ObjectMapper mapper = new ObjectMapper();
        // 忽略json中多出来的属性
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        LoginParameter loginParameter = mapper.readValue(request.getInputStream(), LoginParameter.class);
        log.info("用户登录参数：{}", JSON.toJSONString(loginParameter));

        // 判断请求类型是否指定
        if (Objects.isNull(loginParameter.getLoginType())) {
            throw new IllegalArgumentException("loginType is required");
        }

        // 判断请求来源是否指定
        if (Objects.isNull(loginParameter.getLoginSource())) {
            throw new IllegalArgumentException("loginSource is required");
        }

        // 获取认证对象
        Authentication authentication = loginParameter.getAuthentication();

        // 认证前处理
        if (Objects.nonNull(loginPostProcessors)) {
            for (LoginPostProcessor<Authentication> loginPostProcessor : loginPostProcessors) {
                if (loginPostProcessor.supports(authentication.getClass())) {
                    // 登录参数
                    loginPostProcessor.prePostProcess(loginParameter);
                }
            }
        }

        // 执行认证
        Authentication authenticate = this.getAuthenticationManager().authenticate(authentication);
        authenticate.setAuthenticated(true);

        // 认证后处理
        if (Objects.nonNull(loginPostProcessors)) {
            for (LoginPostProcessor<Authentication> loginPostProcessor : loginPostProcessors) {
                if (loginPostProcessor.supports(authentication.getClass())) {
                    // 传入认证完成的对象
                    loginPostProcessor.postPostProcess(authenticate);
                }
            }
        }
        return authenticate;
    }

    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
    }

}
